package interfaze;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;

import entities.Player;

import logic.Utilities;

/**Global Leader Board Panel's class.
 * @author Team 1
 *
 */
@SuppressWarnings("serial")
public class GlobalLeaderBoardPanel extends JPanel implements ActionListener, MouseListener, ItemListener {
	
	SuperArcade2in1 window;													//The JFrame in which the panel is being added.
	private JLabel background1 = new JLabel();								//One part of the background.
	private JLabel background2 = new JLabel();								//The other part of the background.
	private JTable tLeaderBoard = new JTable();								//The table of the panel.
	private JPanel tablePanel = new JPanel();								//The panel where the table is located.
	private JLabel lShow = new JLabel("Show:");								//A text label.
	private JCheckBox cbOnlyMines = new JCheckBox("Only Mine's");			//A check box to filter user's scores.
	private JRadioButton rbMaxRecords = new JRadioButton("Maximum records", true);	//A radio button to select a filter.
	private JLabel lSearch = new JLabel("First found by name:");			//A text label.
	private JTextField tfSearch = new JTextField();							//The text field to search a player.
	private JButton bSearch = new JButton("Search");						//The button that starts the search.
	private JButton bBack = new JButton("Back");							//The back button.
	private Font font;													//The font for the table, labels and buttons.
	private DefaultTableModel model = new DefaultTableModel(0, 3);			//The model for the table.
	
	/**GlobalLeaderBoardPanel's Constructor
	 * @param window : The JFrame in which the panel is being added.
	 */
	public GlobalLeaderBoardPanel(SuperArcade2in1 window) {
		this.window = window;
		
		//Sets the layout to null in order to work with absolute coordinates.
		this.setLayout(null);
		
		//Sets the font for all the labels, table and buttons.
		font = new Font("Helvetica", Font.PLAIN, Math.round(12 * window.xScale));
		
		//Sets all the components of the panel.
		tablePanel.setBounds(Math.round(300 * window.xScale), Math.round(50 * window.yScale),
				Math.round(900 * window.xScale), Math.round(600 * window.yScale));
		tablePanel.setLayout(null);
		
		tLeaderBoard.setFont(font);
		tLeaderBoard.setShowGrid(true);
		tLeaderBoard.setShowHorizontalLines(true);
		tLeaderBoard.setShowVerticalLines(true);
		
		tablePanel.setLayout( new BorderLayout() );
		tablePanel.add( new JScrollPane(tLeaderBoard), BorderLayout.CENTER);
		
		model.setColumnIdentifiers(new String[] {"Position", "Nick", "Score"});
		
		//Loads the model with the requested data from the database.
		loadModel(database.Search.globalRanking());
		tLeaderBoard.setModel(model);
		tLeaderBoard.getTableHeader().setFont(font);
		tLeaderBoard.getTableHeader().setReorderingAllowed(false);
		tLeaderBoard.getTableHeader().setEnabled(false);
		tLeaderBoard.setEnabled(false);
		
		lShow.setBounds(Math.round(25 * window.xScale), Math.round(50 * window.yScale),
				Math.round(50 * window.xScale), Math.round(25 * window.yScale));
		lShow.setFont(font);
		lShow.setForeground(Color.WHITE);
		
		cbOnlyMines.setBounds(Math.round(125 * window.xScale), Math.round(50 * window.yScale), 
				Math.round(110 * window.xScale), Math.round(25 * window.yScale));
		cbOnlyMines.setForeground(Color.WHITE);
		cbOnlyMines.setFont(font);
		cbOnlyMines.setOpaque(false);
		
		rbMaxRecords.setBounds(Math.round(33 * window.xScale), Math.round(75 * window.yScale),
				Math.round(150 * window.xScale), Math.round(25 * window.yScale));
		rbMaxRecords.setFont(font);
		rbMaxRecords.setForeground(Color.WHITE);
		rbMaxRecords.setOpaque(false);
		
		lSearch.setBounds(Math.round(25 * window.xScale), Math.round(125 * window.yScale),
				Math.round(130 * window.xScale), Math.round(25 * window.yScale));
		lSearch.setFont(font);
		lSearch.setForeground(Color.WHITE);
				
		tfSearch.setBounds(Math.round(150 * window.xScale), Math.round(125 * window.yScale),
				Math.round(120 * window.xScale), Math.round(25 * window.yScale));
		tfSearch.setFont(font);
		
		bSearch.setBounds(Math.round(25 * window.xScale), Math.round(150 * window.yScale), 
				Math.round(100 * window.xScale), Math.round(25 * window.yScale));
		bSearch.setFont(font);
		
		bBack.setBounds(Math.round(25 * window.xScale), Math.round(625 * window.yScale),
				Math.round(100 * window.xScale), Math.round(25 * window.yScale));
		bBack.setFont(font);
		
		//Sets the Background
		Image image = logic.Utilities.loadImage("res/BrickBreakerOn.png");
		if(window.xScale != 1 || window.yScale != 1) {
			image = Utilities.resizeImage(window.xScale, window.yScale, "res/BrickBreakerOn.png");
		}
		background1.setIcon(new ImageIcon(image));
		background1.setBounds(0, 0, image.getWidth(null), image.getHeight(null));
		
		image = logic.Utilities.loadImage("res/EarthDefenderOn.png");
		if(window.xScale != 1 || window.yScale != 1) {
			image = Utilities.resizeImage(window.xScale, window.yScale, "res/EarthDefenderOn.png");
		}
		background2.setIcon(new ImageIcon(image));
		background2.setBounds(0, 0, image.getWidth(null), image.getHeight(null));
		
		//Adds all the components to the panel.
		this.add(lShow);
		this.add(cbOnlyMines);
		this.add(rbMaxRecords);
		this.add(lSearch);
		this.add(tfSearch);
		this.add(bSearch);
		this.add(bBack);
		this.add(tablePanel);
		this.add(background1);
		this.add(background2);
		
		//Adds all the listeners to components.
		cbOnlyMines.addItemListener(this);
		rbMaxRecords.addItemListener(this);
		bSearch.addActionListener(this);
		bSearch.addMouseListener(this);
		bBack.addActionListener(this);
		bBack.addMouseListener(this);
		
		//Request the focus to fix a bug when is full screened.
		tfSearch.requestFocus();
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if(e.getSource().equals(bSearch)) {
			if(tfSearch.getText().length() > 0) {
				for(int i = 0; i < model.getRowCount(); i++) {
					//Search for the user of the text field.
					if(tfSearch.getText().equals(model.getValueAt(i, 1))) {
						//Highlight the result and auto scroll to the result position.
						showSearchResult(i, 1);
						return;
					}
				}
			}
		}else if(e.getSource().equals(bBack)) {
			//Redirects to the main menu panel.
			window.add(new GlobalMenuPanel(window));
			this.setVisible(false);
			window.remove(this);
		}
	}
	
	/** Load the model with the records of the provided list.
	 * @param list : the list of the records to be added.
	 */
	public void loadModel(ArrayList<Player> list) {
		for (int i = 0; i < list.size(); i++) {
			Player temp = list.get(i);
			model.addRow(new Object[] {i+1, temp.getName(), temp.getScore() });
		}
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		//Increases the buttons size when the mouse enters them.
		if(e.getSource().equals(bSearch)) {
			Utilities.buttonEffect(bSearch, 5, window.xScale, window.yScale);
		} else if(e.getSource().equals(bBack)) {
			Utilities.buttonEffect(bBack, 5, window.xScale, window.yScale);
		}
	}

	@Override
	public void mouseExited(MouseEvent e) {
		//Decreases the buttons size when the mouse enters them.
		if(e.getSource().equals(bSearch)) {
			Utilities.buttonEffect(bSearch, -5, window.xScale, window.yScale);
		} else if(e.getSource().equals(bBack)) {
			Utilities.buttonEffect(bBack, -5, window.xScale, window.yScale);
		}
	}

	private void showSearchResult(int row, int col) {
		//If there was a selected value cleans it.
		if(tLeaderBoard.getSelectedRow() != -1) {
			tLeaderBoard.clearSelection();
		}
		//Sets the selection of the search.
		tLeaderBoard.getSelectionModel().setSelectionInterval(row, row);
		//Auto scroll to the searched row.
		Rectangle r = tLeaderBoard.getCellRect(row, col, false);  
        tLeaderBoard.scrollRectToVisible(r);  
        tLeaderBoard.repaint();  
		
	}
	
	@Override
	public void itemStateChanged(ItemEvent e) {
		if(e.getSource().equals(rbMaxRecords)) {
			rbMaxRecords.setSelected(true);
		} else if(e.getSource().equals(cbOnlyMines)) {
			//Removes all the data of the model.
			for(int i = model.getRowCount() - 1; i >= 0; i--) {
				model.removeRow(i);
			}
			if(cbOnlyMines.isSelected()) {
				//Disables the search function.
				lSearch.setVisible(false);
				tfSearch.setVisible(false);
				bSearch.setVisible(false);
				//Loads the global max score of logged user.
				ArrayList<Player> player = new ArrayList<Player>();
				player.add(database.Search.globalRanking(window.userName));
				loadModel(player);
			} else {
				//Enables the search function.
				lSearch.setVisible(true);
				tfSearch.setVisible(true);
				bSearch.setVisible(true);
				//Loads the global max score of all the registered users.
				loadModel(database.Search.globalRanking());
			}
		}
	}
	
	@Override
	public void mousePressed(MouseEvent e) {
		
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		
	}
	
	@Override
	public void mouseReleased(MouseEvent e) {
		
	}
}
